//
// Created by limo on 2025/9/26.
//

#pragma once

#include <boost/asio.hpp>
#include <deque>
#include "connection.h"

// 导入 boost::asio
using boost::asio::ip::tcp;

namespace net {

    class TcpConnection : public Connection {
    public:
        // 构造函数：接受一个 io_context 和 socket
        TcpConnection(boost::asio::io_context& io_context)
                : m_socket(io_context),
                  m_readBuffer(DEFAULT_FRAME_SIZE),
                  m_writeStrand(io_context.get_executor()) {

        }

        TcpConnection(boost::asio::io_context& io_context, tcp::socket socket)
                : m_socket(std::move(socket)),
                  m_readBuffer(DEFAULT_FRAME_SIZE),
                  m_writeStrand(io_context.get_executor()) {

        }

        tcp::socket& socket() {
            return m_socket;
        }

        void setCodec(std::unique_ptr<MessageCodec> codec) override {
            m_codec = std::move(codec);
        }

        void start() override {
            updateState(ConnectionState::Connected);
            doRead(); // 开始异步读取
        }

        void send(const std::string &data) override {
            // 将 std::string 转换为 Buffer 并调用核心虚函数
            // C++11/14: 使用迭代器构造
            Buffer buffer(data.begin(), data.end());
            send(buffer);
        }

        void send(const char *data, size_t length) override {
            // 将 const char* 转换为 Buffer 并调用核心虚函数
            // C++11/14: 使用指针和长度构造
            // ⚠️ 注意：这里我们将 char* 转换到 uint8_t*
            const uint8_t* uint8_data = reinterpret_cast<const uint8_t*>(data);
            Buffer buffer(uint8_data, uint8_data + length);
            send(buffer);
        }

        void send(const Buffer& data) override {
            if (!m_codec || getState() != ConnectionState::Connected) {
                return;
            }
            Buffer packet = m_codec->encode(data);

            boost::asio::post(m_writeStrand,
                              [self = std::static_pointer_cast<TcpConnection>(shared_from_this()), packet = std::move(packet)]() mutable {
                                  // 1. 数据包入队
                                  self->m_writeQueue.push_back(std::move(packet));

                                  // 2. 如果当前没有写操作正在进行，则启动写操作
                                  if (!self->m_isWriting) {
                                      self->m_isWriting = true;
                                      self->doWrite();
                                  }
                              });
        }

        void setMessageReceiver(MessageHandler handler) override {
            m_messageHandler = handler;
        }

        void setErrorHandler(ErrorHandler handler) override {
            m_errorHandler = handler;
        }

        void setStateChangeHandler(StateChangeHandler handler) override {
            m_stateChangeHandler = handler;
        }

        ConnectionState getState() const override {
            return m_currentState;
        }

        ConnectionType getType() const override {
            return ConnectionType::TCP;
        }

        void close() override {
            if (m_currentState != ConnectionState::Closing && m_currentState != ConnectionState::Disconnected) {
                updateState(ConnectionState::Closing);

                // 安全地关闭 socket
                boost::system::error_code ec;
                m_socket.shutdown(tcp::socket::shutdown_both, ec);
                m_socket.close(ec);

                updateState(ConnectionState::Disconnected);
            }
        }


    private:
        // Asio Strand：确保所有写操作串行执行
        boost::asio::strand<boost::asio::io_context::executor_type> m_writeStrand;
        // 写消息队列：存储已编码、待发送的完整数据包
        std::deque<Buffer> m_writeQueue;
        // 标记，指示是否正在进行异步写操作
        bool m_isWriting = false;

        tcp::socket m_socket;
        std::vector<uint8_t> m_readBuffer; // 接收缓冲区

        void processData(size_t bytes_transferred) {
            if (!m_codec) {
                return;
            }
            std::vector<Buffer> messages;

            // 调用抽象编解码器的 decode 方法
            if (m_codec->decode(m_readBuffer.data(), bytes_transferred, messages)) {
                // 遍历并分发所有解析出的完整消息
                for (const auto& msg : messages) {
                    if (m_messageHandler) {
                        m_messageHandler(shared_from_this(), msg, msg.size());
                    }
                }
            }
        }

        // 异步读取数据
        void doRead() {
            auto self(std::static_pointer_cast<TcpConnection>(shared_from_this()));
            m_socket.async_read_some(
                    boost::asio::buffer(m_readBuffer),
                    [this, self](boost::system::error_code ec, std::size_t length) {
                        if (!ec) {
                            processData(length);
                            doRead(); // 继续等待下一轮读取
                        } else {
                            if (self->m_errorHandler) {
                                self->m_errorHandler(self, ec);
                            }
                            self->close();
                        }
                    });
        }

        // 处理写队列中的数据**
        void doWrite() {
            if (m_writeQueue.empty()) {
                // 队列为空，停止写操作
                m_isWriting = false;
                return;
            }

            // 总是发送队列头部的数据包
            const Buffer& packet = m_writeQueue.front();

            auto self(std::static_pointer_cast<TcpConnection>(shared_from_this()));

            boost::asio::async_write(m_socket,
             boost::asio::buffer(packet.data(), packet.size()),
                // 确保回调也在 Strand 上执行，以保证对 m_writeQueue 的修改是安全的
             boost::asio::bind_executor(m_writeStrand,
                    [this, self](boost::system::error_code ec, std::size_t /* length */) {
                        if (!ec) {
                            // 成功发送，移除队列头部
                            self->m_writeQueue.pop_front();
                            // 继续发送下一个数据包
                            self->doWrite();
                        } else {
                            // 发生错误，处理错误并清理连接
                            if (self->m_errorHandler) {
                                self->m_errorHandler(self, ec);
                            }
                            // 错误发生，清除队列并关闭连接
                            self->m_writeQueue.clear();
                            self->m_isWriting = false; // 即使关闭了，也要重置标记
                            self->close();
                        }
                    })
            );
        }
    };

} // net
